﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Security.Cryptography;
using System.Text;

namespace DTcms.Common
{
    public abstract class Sign
    {
        public static string Secret
        {
            get
            {
                return ConfigurationManager.AppSettings["AppUrlSecret"];
            }
        }

        /// <summary>
        /// 根据url取出参数生成签名
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public static string SignRequest(string query)
        {
            //query = UrlEncode(query);
            string[] queryArr = query.Split('?');
            if (queryArr.Length == 2)
            {
                query = queryArr[1];
            }
            else
                return "";
            IDictionary<string, string> queryDict = SplitUrlQuery(query);
            return SignRequest(queryDict, true);
        }

        /// <summary>
        /// 给请求签名。
        /// </summary>
        /// <param name="parameters">所有字符型的请求参数</param>
        /// <returns>签名</returns>
        public static string SignRequest(IDictionary<string, string> parameters)
        {
            return SignRequest(parameters, true);
        }

        /// <summary>
        /// 给请求签名。
        /// </summary>
        /// <param name="parameters">所有字符型的TOP请求参数</param>
        /// <param name="qhs">是否前后都加密钥进行签名</param>
        /// <returns>签名</returns>
        public static string SignRequest(IDictionary<string, string> parameters, bool qhs)
        {
            // 第一步：把字典按Key的字母顺序排序
            IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
            IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();

            // 第二步：把所有参数名和参数值串在一起
            StringBuilder query = new StringBuilder(Secret);
            while (dem.MoveNext())
            {
                string key = dem.Current.Key;
                string value = dem.Current.Value;
                if (!string.IsNullOrEmpty(key) && key.ToLower() != "sign")
                {
                    query.Append(key);
                    if (!string.IsNullOrEmpty(value))
                    {
                        query.Append(value);
                    }
                }
            }
            if (qhs)
            {
                query.Append(Secret);
            }

            // 第三步：使用MD5加密
            MD5 md5 = MD5.Create();
            byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));

            // 第四步：把二进制转化为小写的十六进制
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < bytes.Length; i++)
            {
                result.Append(bytes[i].ToString("x2"));
            }

            return result.ToString();
        }

        /// <summary>
        /// 根据url取出参数
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        private static IDictionary<string, string> SplitUrlQuery(string query)
        {
            IDictionary<string, string> result = new Dictionary<string, string>();

            string[] pairs = query.Split(new char[] { '&' });
            if (pairs != null && pairs.Length > 0)
            {
                foreach (string pair in pairs)
                {
                    string[] oneParam = pair.Split(new char[] { '=' }, 2);
                    if (oneParam != null && oneParam.Length == 2)
                    {
                        result.Add(oneParam[0], oneParam[1]);
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// 编码 
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string UrlEncode(string str)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str); //默认是System.Text.Encoding.Default.GetBytes(str)
            for (int i = 0; i < byStr.Length; i++)
            {
                sb.Append(@"%" + Convert.ToString(byStr[i], 16));
            }
            return (sb.ToString());
        }
    }
}
